﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Fetion.Core
{
    /// <summary>
    /// 基于消息头描述长度分析器
    /// 消息写入的时候会先写入消息总长度(int32),消息类型名称长度(int32),消息类型名称(string)
    /// </summary>
    public abstract class HeadSizeOfPackage : Package
    {
      /// <summary>
      /// 构建分析器
      /// </summary>
        public HeadSizeOfPackage()
        {
            
        }
        protected abstract IMessage ReadMessageByType(BufferReader reader,out object typetag);
        protected abstract void WriteMessageType(IMessage msg, BufferWriter writer);   
        private int mLoad = 0;
        private byte[] sizeData = new byte[4];
        private int sizeDatalength = 0;
        private int _tmpcount;
        private BufferWriter Writer;
        /// <summary>
        /// 导入数据
        /// </summary>
        /// <param name="data">byte数组</param>
        /// <param name="start">写入开始位置</param>
        /// <param name="count">写入总长度</param>
        public override void Import(byte[] data, int start, int count, EventHandler<ClientAsyncCompletedEventArgs<object>> handle)
        {
        
            _tmpcount = count;
            while (_tmpcount > 0)
            {
                if (mLoad == 0)
                {
                    if (_tmpcount < 4)
                    {
                        sizeDatalength = _tmpcount;
                        Buffer.BlockCopy(data, start, sizeData, 0, _tmpcount);
                        _tmpcount = 0;
                        break;
                    }
                    else
                    {

                        Writer = new BufferWriter(Coding);
                        Writer.EnabledVariant = EnabledVariant;
                        if (sizeDatalength == 0)
                        {
                            mLoad = BitConverter.ToInt32(data, start);
                         
                           
                            Writer.Write(data, start, 4);
                            start += 4;
                            mLoad = mLoad - 4;
                            _tmpcount = _tmpcount - 4;
                        }
                        else
                        {
                            int tmps = 4 - sizeDatalength;
                            Buffer.BlockCopy(data, start, sizeData, sizeDatalength, tmps);
                            sizeDatalength = 0;
                            mLoad = BitConverter.ToInt32(sizeData, 0);
                      
                            
                            Writer.Write(sizeData, 0, 4);
                            start += tmps;
                            mLoad = mLoad - 4;
                            _tmpcount = _tmpcount - tmps;
                        }
                    }
                }
                if (_tmpcount >= mLoad)
                {
                    Writer.Write(data, start, mLoad);
                    BufferReader reader = new BufferReader(Coding, Writer);
                    reader.EnabledVariant = EnabledVariant;
                    start += mLoad;
                    _tmpcount = _tmpcount - mLoad;
                    mLoad = 0;
                    MessageRead(reader);
                   
                }
                else
                {
                    Writer.Write(data, start, _tmpcount);
                    mLoad = mLoad - _tmpcount;
                    _tmpcount = 0;

                }
            }
        }
        
        /// <summary>
        /// 消息读取规则,派生类可以重写实现自己的规则
        /// </summary>
        /// <param name="reader">流读取对象</param>
        /// <returns>IMessage</returns>
        public void MessageRead(BufferReader reader)
        {
            IMessage msg = null;
            
            object  typetag;
            reader.Read(4);

            msg = ReadMessageByType(reader, out typetag);
            if (msg == null)
                throw NetTcpException.TypeNotFound(typetag.ToString());
            try
            {
                msg.Load(reader);
            }
            catch (Exception e)
            {
                NetTcpException err = NetTcpException.ObjectLoadError(typetag.ToString(), e);
                throw err;
            }
            OnReceive(msg);
            
        }
        public override byte[] GetMessageData(IMessage e)
        {

            BufferWriter bw = new BufferWriter(Coding);
            bw.EnabledVariant = EnabledVariant;
            ByteArraySegment result = bw.WriteHeadSize();
            WriteMessageType(e, bw);
            e.Save(bw);
            bw.SetHeadSize(bw.Count, result);
            BufferReader reader = new BufferReader(Coding, bw);
            return reader.ToBytes();
        }
    }
}
